import {delay, designComponent, iHTMLDivElement, iTransitionEvent, reactive, SimpleFunction, useModel, useRefs, useStyles, watch} from "@peryl/react-compose";
import {unit} from '@peryl/utils/unit';
import './MenuCollapse.scss';

export const MenuCollapse = designComponent({
  name: 'menu-collapse',
  props: {
    show: { type: Boolean },
    open: { type: Boolean },
  },
  slots: ['default'],
  emits: {
    onTransitionend: () => true,
    onUpdateShow: (val: boolean) => true,
    onUpdateOpen: (val: boolean) => true,
  },
  setup({ props, slots, event: { emit } }) {

    const { refs, onRef } = useRefs({ inner: iHTMLDivElement });

    const showModel = useModel(() => props.show, emit.onUpdateShow);
    const openModel = useModel(() => props.open, emit.onUpdateOpen);

    const state = reactive({
      isRenderEl: showModel.value,
      isRenderSlot: showModel.value,
      height: !props.show ? 0 : null,
      onTransitionend: null as null | SimpleFunction
    });

    const styles = useStyles((styles) => {if (state.height != null) {styles.height = unit(state.height);}});

    watch(() => props.show, (show) => {show ? methods.show() : methods.hide();});

    const methods = {
      show: async () => {
        if (state.height == null) {return;}

        if (!state.isRenderEl) {
          state.isRenderEl = true;
          state.height = 0;
          state.isRenderSlot = true;
          await delay();
        }
        state.height = refs.inner!.offsetHeight;
        state.onTransitionend = () => {
          state.height = null;
          emit.onTransitionend();
          openModel.value = true;
        };
      },
      hide: async () => {
        if (state.height == 0) {return;}
        state.height = refs.inner!.offsetHeight;
        await delay();
        state.height = 0;
        state.onTransitionend = () => {
          state.height = 0;
          state.isRenderEl = false;
          emit.onTransitionend();
          openModel.value = false;
        };
      },
    };

    const handler = {
      onTransitionend: (e: iTransitionEvent) => {
        if (e.target !== e.currentTarget) {return;}
        if (e.propertyName !== 'height') {return;}
        state.onTransitionend?.();
      },
    };

    return () => (
      !!state.isRenderEl && (
        <div style={styles.value} className="menu-collapse" onTransitionEnd={handler.onTransitionend}>
          <div ref={onRef.inner}>
            {state.isRenderSlot && slots.default()}
          </div>
        </div>
      )
    );
  },
});
